home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / bbsutils / smb_110a.arj / FIDO2SMB.C < prev    next >
C/C++ Source or Header  |  1994-03-28  |  15KB  |  502 lines

  1. /* FIDO2SMB.C */
  2.  
  3. /* Converts FidoNet FTSC-1 (*.MSG) message base to SMB format */
  4.  
  5. /* The intention of this source code is an example of how to use the SMBLIB */
  6. /* library functions to access an SMB format message base.                    */
  7.  
  8. /* This program and source code are freeware. May be used in part or whole    */
  9. /* for any purpose without consent or notification of Digital Dynamics.     */
  10.  
  11. /* Digital Dynamics does request that developers that release products that */
  12. /* support the SMB format notify Digital Dynamics so the implementation     */
  13. /* and contact chapters in the technical specification may be updated.        */
  14.  
  15. #include "smblib.h"
  16. #include "crc32.h"
  17. #include <dos.h>
  18.                                     /* Attribute bits for fido msg header */
  19. #define FIDO_PRIVATE    (1<<0)        /* Private message */
  20. #define FIDO_CRASH        (1<<1)        /* Crash-mail (send immediately) */
  21. #define FIDO_RECV        (1<<2)        /* Received successfully */
  22. #define FIDO_SENT        (1<<3)        /* Sent successfully */
  23. #define FIDO_FILE        (1<<4)        /* File attached */
  24. #define FIDO_INTRANS    (1<<5)        /* In transit */
  25. #define FIDO_ORPHAN     (1<<6)        /* Orphan */
  26. #define FIDO_KILLSENT    (1<<7)        /* Kill it after sending it */
  27. #define FIDO_LOCAL        (1<<8)        /* Created locally - on this system */
  28. #define FIDO_HOLD        (1<<9)        /* Hold - don't send it yet */
  29. #define FIDO_FREQ        (1<<11)     /* File request */
  30. #define FIDO_RRREQ        (1<<12)     /* Return receipt request */
  31. #define FIDO_RR         (1<<13)     /* This is a return receipt */
  32. #define FIDO_AUDIT        (1<<14)     /* Audit request */
  33. #define FIDO_FUPREQ     (1<<15)     /* File update request */
  34.  
  35. typedef struct {                        /* FidoNet msg header */
  36.     uchar    from[36],                    /* From user */
  37.             to[36],                     /* To user */
  38.             subj[72],                    /* Message title */
  39.             time[20];                    /* Time in goof-ball ASCII format */
  40.     short    read,                        /* Times read */
  41.             destnode,                    /* Destination node */
  42.             orignode,                    /* Origin node */
  43.             cost,                        /* Cost in pennies */
  44.             orignet,                    /* Origin net */
  45.             destnet,                    /* Destination net */
  46.             destzone,                    /* Destination zone */
  47.             origzone,                    /* Origin zone */
  48.             destpoint,                    /* Destination point */
  49.             origpoint,                    /* Origin point */
  50.             re,                         /* Message number regarding */
  51.             attr,                        /* Attributes - see FIDO_* */
  52.             next;                        /* Next message number in stream */
  53.             } fmsghdr_t;
  54.  
  55. /******************************************/
  56. /* CRC-16 routines required for SMB index */
  57. /******************************************/
  58.  
  59. /****************************************************************************/
  60. /* Updates 16-bit "rcrc" with character 'ch'                                */
  61. /****************************************************************************/
  62. void ucrc16(uchar ch, ushort *rcrc) {
  63.     ushort i, cy;
  64.     uchar nch=ch;
  65.  
  66. for (i=0; i<8; i++) {
  67.     cy=*rcrc & 0x8000;
  68.     *rcrc<<=1;
  69.     if (nch & 0x80) *rcrc |= 1;
  70.     nch<<=1;
  71.     if (cy) *rcrc ^= 0x1021; }
  72. }
  73.  
  74. /****************************************************************************/
  75. /* Returns 16-crc of string (not counting terminating NULL)                 */
  76. /****************************************************************************/
  77. ushort crc16(char *str)
  78. {
  79.     int     i=0;
  80.     ushort    crc=0;
  81.  
  82. ucrc16(0,&crc);
  83. while(str[i])
  84.     ucrc16(str[i++],&crc);
  85. ucrc16(0,&crc);
  86. ucrc16(0,&crc);
  87. return(crc);
  88. }
  89.  
  90. /****************************************************************************/
  91. /* Truncates white-space chars off end of 'str' and terminates at first tab */
  92. /****************************************************************************/
  93. void truncsp(char *str)
  94. {
  95.     char c;
  96.  
  97. str[strcspn(str,"\t")]=0;
  98. c=strlen(str);
  99. while(c && (uchar)str[c-1]<=' ') c--;
  100. str[c]=0;
  101. }
  102.  
  103. /****************************************************************************/
  104. /* Returns the length of the file in 'filespec'                             */
  105. /****************************************************************************/
  106. long flength(char *filespec)
  107. {
  108.     struct ffblk f;
  109.  
  110. if(findfirst(filespec,&f,0)==0)
  111.     return(f.ff_fsize);
  112. return(-1L);
  113. }
  114.  
  115. /****************************************************************************/
  116. /* Returns the FidoNet address kept in str as ASCII.                        */
  117. /****************************************************************************/
  118. fidoaddr_t atofaddr(char *str)
  119. {
  120.     char *p;
  121.     fidoaddr_t addr;
  122.  
  123. addr.zone=addr.net=addr.node=addr.point=0;
  124. if((p=strchr(str,':'))!=NULL) {
  125.     addr.zone=atoi(str);
  126.     addr.net=atoi(p+1); }
  127. else {
  128.     addr.zone=1;
  129.     addr.net=atoi(str); }
  130. if(!addr.zone)                /* no such thing as zone 0 */
  131.     addr.zone=1;
  132. if((p=strchr(str,'/'))!=NULL)
  133.     addr.node=atoi(p+1);
  134. else {
  135.     addr.net=1;
  136.     addr.node=atoi(str); }
  137. if((p=strchr(str,'.'))!=NULL)
  138.     addr.point=atoi(p+1);
  139. return(addr);
  140. }
  141.  
  142. /****************************************************************************/
  143. /* Converts goofy FidoNet time format into Unix format                        */
  144. /****************************************************************************/
  145. time_t fmsgtime(char *str)
  146. {
  147.     char month[4];
  148.     struct date date;
  149.     struct time t;
  150.  
  151. if(isdigit(str[1])) {    /* Regular format: "01 Jan 86  02:34:56" */
  152.     date.da_day=atoi(str);
  153.     sprintf(month,"%3.3s",str+3);
  154.     if(!stricmp(month,"jan"))
  155.         date.da_mon=1;
  156.     else if(!stricmp(month,"feb"))
  157.         date.da_mon=2;
  158.     else if(!stricmp(month,"mar"))
  159.         date.da_mon=3;
  160.     else if(!stricmp(month,"apr"))
  161.         date.da_mon=4;
  162.     else if(!stricmp(month,"may"))
  163.         date.da_mon=5;
  164.     else if(!stricmp(month,"jun"))
  165.         date.da_mon=6;
  166.     else if(!stricmp(month,"jul"))
  167.         date.da_mon=7;
  168.     else if(!stricmp(month,"aug"))
  169.         date.da_mon=8;
  170.     else if(!stricmp(month,"sep"))
  171.         date.da_mon=9;
  172.     else if(!stricmp(month,"oct"))
  173.         date.da_mon=10;
  174.     else if(!stricmp(month,"nov"))
  175.         date.da_mon=11;
  176.     else
  177.         date.da_mon=12;
  178.     date.da_year=1900+atoi(str+7);
  179.     t.ti_hour=atoi(str+11);
  180.     t.ti_min=atoi(str+14);
  181.     t.ti_sec=atoi(str+17); }
  182.  
  183. else {                    /* SEAdog  format: "Mon  1 Jan 86 02:34" */
  184.     date.da_day=atoi(str+4);
  185.     sprintf(month,"%3.3s",str+7);
  186.     if(!stricmp(month,"jan"))
  187.         date.da_mon=1;
  188.     else if(!stricmp(month,"feb"))
  189.         date.da_mon=2;
  190.     else if(!stricmp(month,"mar"))
  191.         date.da_mon=3;
  192.     else if(!stricmp(month,"apr"))
  193.         date.da_mon=4;
  194.     else if(!stricmp(month,"may"))
  195.         date.da_mon=5;
  196.     else if(!stricmp(month,"jun"))
  197.         date.da_mon=6;
  198.     else if(!stricmp(month,"jul"))
  199.         date.da_mon=7;
  200.     else if(!stricmp(month,"aug"))
  201.         date.da_mon=8;
  202.     else if(!stricmp(month,"sep"))
  203.         date.da_mon=9;
  204.     else if(!stricmp(month,"oct"))
  205.         date.da_mon=10;
  206.     else if(!stricmp(month,"nov"))
  207.         date.da_mon=11;
  208.     else
  209.         date.da_mon=12;
  210.     date.da_year=1900+atoi(str+11);
  211.     t.ti_hour=atoi(str+14);
  212.     t.ti_min=atoi(str+17);
  213.     t.ti_sec=0; }
  214. return(dostounix(&date,&t));
  215. }
  216.  
  217. /****************************************************************************/
  218. /* Entry point - if you didn't know that, maybe you shouldn't be reading :) */
  219. /****************************************************************************/
  220. int main(int argc, char **argv)
  221. {
  222.     uchar    *p,str[128],*fbuf,*sbody,*stail,ch,done;
  223.     ushort    xlat,net;
  224.     int     i,j,file,col,cr,esc,orig,last,msgs,found;
  225.     ulong    l,m,length,bodylen,taillen,crc;
  226.     struct    ffblk ff;
  227.     smbmsg_t    msg;
  228.     smbstatus_t status;
  229.     fmsghdr_t    fmsghdr;
  230.     fidoaddr_t    destaddr,origaddr,faddr;
  231.  
  232. if(argc<3) {
  233.     printf("usage: fido2smb <fido_dir> <smb_name>\r\n");
  234.     exit(1); }
  235.  
  236. strcpy(smb_file,argv[2]);
  237. strupr(smb_file);
  238.  
  239. smb_open(10);
  240. if(!filelength(fileno(shd_fp)))
  241.     smb_create(2000,2000,0,10);
  242.  
  243. smb_getstatus(&status);       // Initialized for first call to smb_addcrc()
  244.  
  245. /*********************************************/
  246. /* Get the total number of .MSG files in dir */
  247. /*********************************************/
  248. printf("\nCounting messages...");
  249. sprintf(str,"%s\\*.MSG",argv[1]);
  250. last=findfirst(str,&ff,0);
  251. for(msgs=0;!last;msgs++)
  252.     last=findnext(&ff);
  253. printf("\n%u messages.\n",msgs);
  254.  
  255. /******************************************/
  256. /* Convert in sequence, starting at 1.MSG */
  257. /******************************************/
  258. for(i=1,found=0;found<msgs && i<2000;i++) {
  259.     sprintf(str,"%s\\%u.MSG",argv[1],i);
  260.     if((file=open(str,O_RDONLY|O_BINARY))==-1)
  261.         continue;
  262.     found++;
  263.     strupr(str);
  264.     printf("%s\n",str);
  265.     read(file,&fmsghdr,sizeof(fmsghdr_t));
  266.     memset(&msg,0,sizeof(smbmsg_t));
  267.     memcpy(msg.hdr.id,"SHD\x1a",4);
  268.     msg.hdr.version=SMB_VERSION;
  269.     if(fmsghdr.attr&FIDO_PRIVATE)
  270.         msg.idx.attr|=MSG_PRIVATE;
  271.     msg.hdr.attr=msg.idx.attr;
  272.  
  273.     msg.hdr.when_imported.time=time(NULL);
  274.     msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
  275.  
  276.     origaddr.zone=fmsghdr.origzone;     /* only valid if NetMail */
  277.     origaddr.net=fmsghdr.orignet;
  278.     origaddr.node=fmsghdr.orignode;
  279.     origaddr.point=fmsghdr.origpoint;
  280.  
  281.     destaddr.zone=fmsghdr.destzone;     /* only valid if NetMail */
  282.     destaddr.net=fmsghdr.destnet;
  283.     destaddr.node=fmsghdr.destnode;
  284.     destaddr.point=fmsghdr.destpoint;
  285.  
  286.     smb_hfield(&msg,SENDER,strlen(fmsghdr.from),fmsghdr.from);
  287.     strlwr(fmsghdr.from);
  288.     msg.idx.from=crc16(fmsghdr.from);
  289.  
  290.     smb_hfield(&msg,RECIPIENT,strlen(fmsghdr.to),fmsghdr.to);
  291.     strlwr(fmsghdr.to);
  292.     msg.idx.to=crc16(fmsghdr.to);
  293.  
  294.     smb_hfield(&msg,SUBJECT,strlen(fmsghdr.subj),fmsghdr.subj);
  295.     strlwr(fmsghdr.subj);
  296.     msg.idx.subj=crc16(fmsghdr.subj);
  297.  
  298.     length=filelength(file)-sizeof(fmsghdr_t);
  299.     if((fbuf=(char *)MALLOC(length))==NULL) {
  300.         printf("alloc error\n");
  301.         exit(1); }
  302.     if((sbody=(char *)MALLOC(length*2L))==NULL) {
  303.         printf("alloc error\n");
  304.         exit(1); }
  305.     if((stail=(char *)MALLOC(length))==NULL) {
  306.         printf("alloc error\n");
  307.         exit(1); }
  308.     read(file,fbuf,length);
  309.     close(file);
  310.  
  311.     for(col=l=esc=done=bodylen=taillen=orig=0,cr=1;l<length;l++) {
  312.         ch=fbuf[l];
  313.         if(ch==1 && cr) {    /* kludge line */
  314.  
  315.             if(!strncmp(fbuf+l+1,"TOPT ",5))
  316.                 destaddr.point=atoi(fbuf+l+6);
  317.  
  318.             else if(!strncmp(fbuf+l+1,"FMPT ",5))
  319.                 origaddr.point=atoi(fbuf+l+6);
  320.  
  321.             else if(!strncmp(fbuf+l+1,"INTL ",5)) {
  322.                 faddr=atofaddr(fbuf+l+6);
  323.                 destaddr.zone=faddr.zone;
  324.                 destaddr.net=faddr.net;
  325.                 destaddr.node=faddr.node;
  326.                 l+=6;
  327.                 while(l<length && fbuf[l]!=SP) l++;
  328.                 faddr=atofaddr(fbuf+l+1);
  329.                 origaddr.zone=faddr.zone;
  330.                 origaddr.net=faddr.net;
  331.                 origaddr.node=faddr.node; }
  332.  
  333.             else if(!strncmp(fbuf+l+1,"MSGID:",6)) {
  334.                 l+=7;
  335.                 while(l<length && fbuf[l]<=SP) l++;
  336.                 m=l;
  337.                 while(m<length && fbuf[m]!=CR) m++;
  338.                 while(m && fbuf[m-1]<=SP) m--;
  339.                 if(m>l)
  340.                     smb_hfield(&msg,FIDOMSGID,m-l,fbuf+l); }
  341.  
  342.             else if(!strncmp(fbuf+l+1,"REPLY:",6)) {
  343.                 l+=7;
  344.                 while(l<length && fbuf[l]<=SP) l++;
  345.                 m=l;
  346.                 while(m<length && fbuf[m]!=CR) m++;
  347.                 while(m && fbuf[m-1]<=SP) m--;
  348.                 if(m>l)
  349.                     smb_hfield(&msg,FIDOREPLYID,m-l,fbuf+l); }
  350.  
  351.             else if(!strncmp(fbuf+l+1,"FLAGS:",6)) {
  352.                 l+=7;
  353.                 while(l<length && fbuf[l]<=SP) l++;
  354.                 m=l;
  355.                 while(m<length && fbuf[m]!=CR) m++;
  356.                 while(m && fbuf[m-1]<=SP) m--;
  357.                 if(m>l)
  358.                     smb_hfield(&msg,FIDOFLAGS,m-l,fbuf+l); }
  359.  
  360.             else if(!strncmp(fbuf+l+1,"PATH:",5)) {
  361.                 l+=6;
  362.                 while(l<length && fbuf[l]<=SP) l++;
  363.                 m=l;
  364.                 while(m<length && fbuf[m]!=CR) m++;
  365.                 while(m && fbuf[m-1]<=SP) m--;
  366.                 if(m>l)
  367.                     smb_hfield(&msg,FIDOPATH,m-l,fbuf+l); }
  368.  
  369.             else if(!strncmp(fbuf+l+1,"PID:",4)) {
  370.                 l+=5;
  371.                 while(l<length && fbuf[l]<=SP) l++;
  372.                 m=l;
  373.                 while(m<length && fbuf[m]!=CR) m++;
  374.                 while(m && fbuf[m-1]<=SP) m--;
  375.                 if(m>l)
  376.                     smb_hfield(&msg,FIDOPID,m-l,fbuf+l); }
  377.  
  378.             else {        /* Unknown kludge line */
  379.                 while(l<length && fbuf[l]<=SP) l++;
  380.                 m=l;
  381.                 while(m<length && fbuf[m]!=CR) m++;
  382.                 while(m && fbuf[m-1]<=SP) m--;
  383.                 if(m>l)
  384.                     smb_hfield(&msg,FIDOCTRL,m-l,fbuf+l); }
  385.  
  386.             while(l<length && fbuf[l]!=CR) l++;
  387.             continue; }
  388.  
  389.         if(ch!=LF && ch!=0x8d) {    /* ignore LF and soft CRs */
  390.             if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
  391.                 || !strncmp((char *)fbuf+l,"---\r",4)))
  392.                 done=1;             /* tear line and down go into tail */
  393.             if(done && cr && !strncmp(fbuf+l,"SEEN-BY:",8)) {
  394.                 l+=8;
  395.                 while(l<length && fbuf[l]<=SP) l++;
  396.                 m=l;
  397.                 while(m<length && fbuf[m]!=CR) m++;
  398.                 while(m && fbuf[m-1]<=SP) m--;
  399.                 if(m>l)
  400.                     smb_hfield(&msg,FIDOSEENBY,m-l,fbuf+l);
  401.                 while(l<length && fbuf[l]!=CR) l++;
  402.                 continue;  }  /* skip the CR */
  403.             if(done)
  404.                 stail[taillen++]=ch;
  405.             else
  406.                 sbody[bodylen++]=ch;
  407.             col++;
  408.             if(ch==CR) {
  409.                 cr=1;
  410.                 col=0;
  411.                 if(done)
  412.                     stail[taillen++]=LF;
  413.                 else
  414.                     sbody[bodylen++]=LF; }
  415.             else {
  416.                 cr=0;
  417.                 if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
  418.                     p=strchr(fbuf+l+11,CR);      /* find carriage return */
  419.                     while(p && *p!='(') p--;     /* rewind to '(' */
  420.                     if(p)
  421.                         origaddr=atofaddr(p+1);     /* get orig address */
  422.                     orig=done=1; }
  423.                 if(done)
  424.                     continue;
  425.  
  426.                 if(ch==ESC) esc=1;        /* ANSI codes */
  427.                 if(ch==SP && col>40 && !esc) {    /* word wrap */
  428.                     for(m=l+1;m<length;m++)     /* find next space */
  429.                         if(fbuf[m]<=SP)
  430.                             break;
  431.                     if(m<length && m-l>80-col) {  /* if it's beyond the eol */
  432.                         sbody[bodylen++]=CR;
  433.                         sbody[bodylen++]=LF;
  434.                         col=0; } }
  435.                 } } }
  436.  
  437.     if(bodylen>=2 && sbody[bodylen-2]==CR && sbody[bodylen-1]==LF)
  438.         bodylen-=2;                         /* remove last CRLF if present */
  439.  
  440.     for(l=0,crc=0xffffffff;l<bodylen;l++)
  441.         crc=ucrc32(sbody[l],crc);
  442.     crc=~crc;
  443.  
  444.     j=smb_addcrc(status.max_crcs,crc,10);
  445.     if(j) {
  446.         if(j==1) {
  447.             printf("\nDuplicate message\n");
  448.             smb_freemsgmem(msg);
  449.             FREE(fbuf);
  450.             FREE(sbody);
  451.             FREE(stail);
  452.             continue; }
  453.         printf("smb_addcrc returned %d\n",j);
  454.         exit(1); }
  455.  
  456.     while(taillen && stail[taillen-1]<=SP)    /* trim all garbage off the tail */
  457.         taillen--;
  458.  
  459.     net=NET_FIDO;    /* Record origin address */
  460.     smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
  461.     smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr);
  462.  
  463.     if(!orig) {     /* No origin line means NetMail, so add dest addr */
  464.         smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
  465.         smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr); }
  466.  
  467.     if(smb_open_da(10)) {
  468.         printf("error opening %s.SDA\n",smb_file);
  469.         exit(1); }
  470.     l=bodylen+2;
  471.     if(taillen)
  472.         l+=(taillen+2);
  473.     msg.hdr.offset=smb_fallocdat(l,1);
  474.     fclose(sda_fp);
  475.     if(msg.hdr.offset && msg.hdr.offset<1L) {
  476.         printf("error %ld allocating records\r\n",msg.hdr.offset);
  477.         exit(1); }
  478.     fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
  479.     xlat=XLAT_NONE;
  480.     fwrite(&xlat,2,1,sdt_fp);
  481.     l=ftell(sdt_fp);
  482.     fwrite(sbody,SDT_BLOCK_LEN,smb_datblocks(bodylen),sdt_fp);
  483.     if(taillen) {
  484.         fseek(sdt_fp,l+bodylen,SEEK_SET);
  485.         fwrite(&xlat,2,1,sdt_fp);
  486.         fwrite(stail,SDT_BLOCK_LEN,smb_datblocks(taillen),sdt_fp); }
  487.     FREE(fbuf);
  488.     FREE(sbody);
  489.     FREE(stail);
  490.  
  491.     smb_dfield(&msg,TEXT_BODY,bodylen+2);
  492.     if(taillen)
  493.         smb_dfield(&msg,TEXT_TAIL,taillen+2);
  494.  
  495.     smb_addmsghdr(&msg,&status,1,10);
  496.     smb_freemsgmem(msg); }
  497.  
  498. printf("\n%u messages converted.\n",found);
  499. return(0);
  500. }
  501.  
  502.